package backend

import (
	"github.com/gin-gonic/gin"
	"net"
	"net/http"
	commonModule "store/backend/common"
	rbacModule "store/backend/rbac"
	"store/bootstrap"
	"store/libs/helper"
	"store/logic/common"
	"store/logic/rbac"
	"strings"
)

var (
	login      = new(rbacModule.Login)
	OperateLog = &common.AdminOperateLogLogic{}
)

func Start(router *gin.Engine) {
	//登录
	router.POST("/admin/login", login.Login)
	//注销登录
	router.GET("/admin/login-out", login.LoginOut)
	//获取权限列表
	router.GET("/admin/rights", login.GetRights)
	//获取验证码
	router.POST("/admin/code", login.Code)

	//附加操作日志
	router.Use(func(ctx *gin.Context) {
		//请求结束
		ctx.Next()

		val, exist := ctx.Get("admin")
		if exist {
			//增加操作日志
			admin := val.(*rbac.LoginInfo)
			route, _ := ctx.Get("route")

			desc, ok := ctx.Get("opt-desc")

			//如果没有设置描述
			if !ok {
				desc = ""
			}

			logItem := map[string]interface{}{
				"admin_id":     admin.Id,
				"admin_name":   admin.AdminName,
				"operate_desc": desc,
				"router":       route,
				"operate_ip":   helper.Ip2long(net.ParseIP(ctx.ClientIP())),
			}

			go func(item map[string]interface{}) {
				OperateLog.Clone(ctx).Add(item)
			}(logItem)
		}
	})

	//common
	com := router.Group("/admin/common")
	com.Use(V1Auth)
	{
		controllerList := []interface{}{
			commonModule.NewOperateController(),
		}

		//自动注册路由
		bootstrap.AutoRegisterRoute(com, controllerList)
	}

	//rbac
	rbacRouter := router.Group("/admin/rbac")
	rbacRouter.Use(V1Auth)
	{
		controllerList := []interface{}{
			rbacModule.NewAdminController(),
			rbacModule.NewAdminRoleController(),
			rbacModule.NewAdminUserRoleController(),
			rbacModule.NewAdminRightsController(),
			rbacModule.NewAdminAccessController(),
		}
		//自动注册路由
		bootstrap.AutoRegisterRoute(rbacRouter, controllerList)
	}
}

func V1Auth(ctx *gin.Context) {
	admin, err := login.GetAdminModel(ctx)
	if err != nil {
		login.ResponseAndAbort(ctx, http.StatusForbidden, err.Error(), nil)
		return
	}

	//解析路由
	route := ctx.Request.RequestURI
	paramStart := strings.Index(route, "?")
	if paramStart > 0 {
		route = route[:paramStart]
	}

	//超管不用鉴权
	if admin.IsSuperAdmin == 1 {
		return
	}

	//获取管理员拥有角色的所有权限id
	rightsIds := rbac.GetRightsIdList(ctx, admin.Id)
	if len(rightsIds) < 1 {
		login.ResponseAndAbort(ctx, http.StatusForbidden, "您没有权限登录", nil)
		return
	}

	routeArr := strings.Split(route[1:], "/")
	length := len(routeArr)
	if length < 3 {
		login.ResponseAndAbort(ctx, http.StatusForbidden, "非法请求", nil)
		return
	}

	module := routeArr[1]
	controller := routeArr[2]
	action := strings.ToLower(ctx.Request.Method)
	if length > 3 {
		action = routeArr[3]
	}

	tree := rbac.GetAllEnableRights(ctx)

	tree, hasModule := checkRight(tree, rightsIds, module)
	if !hasModule {
		login.ResponseAndAbort(ctx, http.StatusForbidden, "没有权限进行该操作", nil)
		return
	}

	tree, hasController := checkRight(tree, rightsIds, controller)
	if !hasController {
		login.ResponseAndAbort(ctx, http.StatusForbidden, "没有权限进行该操作", nil)
		return
	}

	tree, hasAction := checkRight(tree, rightsIds, action)
	if !hasAction {
		login.ResponseAndAbort(ctx, http.StatusForbidden, "没有权限进行该操作", nil)
		return
	}

	//设置路由
	ctx.Set("route", helper.Append(module, "/", controller, "/", action))
}

/**
 * 鉴权
 */
func checkRight(tree *rbac.RightsTree, rightsIds map[uint64]uint8, name string) (*rbac.RightsTree, bool) {
	hasRight := false
	for index, item := range tree.Children {
		if item.Data.Name == name {
			if _, hasRight = rightsIds[item.Data.Id]; hasRight {
				tree = tree.Children[index]
				return tree, true
			}
		}
	}

	return tree, hasRight
}
